package com.yyj.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yyj.constant.BusinessConstants;
import com.yyj.dao.TPropertyAdviceMapper;
import com.yyj.dao.TPropertyPaymentMapper;
import com.yyj.dao.TPropertyRoomMapper;
import com.yyj.enums.OrderStatusEnum;
import com.yyj.enums.PaymentStatusEnum;
import com.yyj.enums.PaymentTypeEnum;
import com.yyj.exception.BaseException;
import com.yyj.model.*;
import com.yyj.pojo.user.SessionInfo;
import com.yyj.util.DateUtil;
import com.yyj.util.WeixinUtil;
import com.yyj.util.security.RandomUtil;
import com.yyj.web.protocol.PageRspData;
import com.yyj.web.protocol.req.*;
import com.yyj.web.protocol.resp.BackendPaymentListResp;
import com.yyj.web.protocol.resp.PaymentQueryResp;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.yyj.util.DateUtil.sdfLongTimePlus;

@Service
public class PaymentService {

    public static Logger log = LoggerFactory.getLogger(PaymentService.class);


    @Autowired
    TPropertyPaymentMapper paymentMapper;

    @Autowired
    UserService userService;

    @Autowired
    WeixinPayService weixinPayService;

    @Autowired
    private FeeConfigService feeConfigService;

    @Autowired
    private TPropertyRoomMapper roomMapper;

    @Autowired
    private ConfigService configService;

    @Autowired
    private AppService appService;

    @Autowired
    UserFormService userFormService;

    @Autowired
    WaterBillService waterBillService;

    @Autowired
    RoomService roomService;

    @Transactional(rollbackFor = Exception.class)
    public void addPayment(PaymentAddReq paymentAddReq){
        TPropertyPayment tPropertyPayment = new TPropertyPayment();
        BeanUtils.copyProperties(paymentAddReq , tPropertyPayment);
        tPropertyPayment.setCreateTime(new Date());
        tPropertyPayment.setUpdateTime(new Date());
        paymentMapper.insert(tPropertyPayment);
    }

    public PaymentQueryResp findPaymentRecord(PaymentQueryReq paymentQueryReq){
        PaymentQueryResp paymentQueryResp = null;
        List<PaymentQueryResp> list = paymentMapper.queryPaymentRecord(paymentQueryReq);
        if(list.size() > 0){
            paymentQueryResp = list.get(0);
        }
        return paymentQueryResp;
    }

    public Integer findPaymentCount(PaymentCountReq paymentCountReq){
        if(PaymentTypeEnum.WATER_FEE.getCode().equals(paymentCountReq.getType())){
            return paymentMapper.queryWaterPaymentNum(paymentCountReq);
        }
        return paymentMapper.queryPaymentNum(paymentCountReq);
    }

    public PageRspData<PaymentQueryResp> findPaymentList(PaymentListReq paymentCountReq) throws Exception {
        PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
        BeanUtils.copyProperties(paymentCountReq , paymentQueryReq);
        return findPaymentList(paymentQueryReq);
    }

    public PaymentQueryResp findPaymentDetail(long id) throws Exception {
        PaymentQueryResp paymentQueryResp = new PaymentQueryResp();
        TPropertyPayment propertyPayment = paymentMapper.selectByPrimaryKey(id);
        BeanUtils.copyProperties(propertyPayment , paymentQueryResp);
        return paymentQueryResp;
    }

    public PageRspData<PaymentQueryResp> findPaymentList(PaymentQueryReq paymentQueryReq) throws Exception{
        Page page = PageHelper.startPage(paymentQueryReq.getCurrentPage(), paymentQueryReq.getPageSize());
        List<PaymentQueryResp> paymentList = paymentMapper.queryPaymentRecord(paymentQueryReq);
        PageRspData<PaymentQueryResp> pageRspData = new PageRspData<PaymentQueryResp>(
                page.getTotal(), paymentQueryReq.getCurrentPage(), paymentQueryReq.getPageSize(), paymentList);
        return pageRspData;
    }

    public TPropertyPayment findPaymentByPayNo(String payNo){
        TPropertyPayment tPropertyPayment = new TPropertyPayment();
        TPropertyPaymentExample paymentExample = new TPropertyPaymentExample();
        TPropertyPaymentExample.Criteria criteria = paymentExample.createCriteria();
        criteria.andPayNoEqualTo(payNo);
        List<TPropertyPayment> paymentList = paymentMapper.selectByExample(paymentExample);
        if(paymentList.size() > 0){
            tPropertyPayment = paymentList.get(0);
        }
        return tPropertyPayment;
    }

    public TPropertyPayment findPaymentByWaterBillId(Long waterBillId){
        TPropertyPayment tPropertyPayment = new TPropertyPayment();
        TPropertyPaymentExample paymentExample = new TPropertyPaymentExample();
        TPropertyPaymentExample.Criteria criteria = paymentExample.createCriteria();
        criteria.andWaterBillIdEqualTo(waterBillId);
        List<TPropertyPayment> paymentList = paymentMapper.selectByExample(paymentExample);
        if(paymentList.size() > 0){
            tPropertyPayment = paymentList.get(0);
        }
        return tPropertyPayment;
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> payBill(PaymentPayReq paymentPayReq , SessionInfo sessionInfo) throws Exception{
        TPropertyPayment paymentObj = paymentMapper.selectByPrimaryKey(paymentPayReq.getPaymentId());
        if(null == paymentObj){
            throw new BaseException("不存在当前类型的缴费记录");
        }
        if(!PaymentStatusEnum.NO_PAY.getCode().equals(paymentObj.getStatus())){
            throw new BaseException("该记录可能正在审核或者已缴费，请联系管理员");
        }
        //生成交易流水号
        String payNo = DateUtil.getCurrDate().replaceAll("-" , "") + RandomUtil.digits(16);
        log.info("wxPay payNo>>>>" + payNo);
        //更新费用表，加入订单号
        paymentObj.setPayNo(payNo);
        paymentObj.setPayStatus(OrderStatusEnum.NO_PAY.getCode());
        paymentObj.setMobile(sessionInfo.getMobile());
        int updateRlt = paymentMapper.updateByPrimaryKeySelective(paymentObj);

        //更新成功调用微信支付
        if(1 == updateRlt){
            WxPayReq wxPayReq = new WxPayReq();
            wxPayReq.setPayNo(payNo);
            wxPayReq.setMoney(paymentObj.getAmount());
            wxPayReq.setFeeDate(paymentObj.getFeeDate());
            wxPayReq.setType(paymentObj.getType());
            wxPayReq.setOpenId(sessionInfo.getOpenId());
            wxPayReq.setRoomNum(sessionInfo.getRoomNum());
            return weixinPayService.dealWxPay(wxPayReq);
        }
        return null;

    }


    @Transactional(rollbackFor = Exception.class)
    public void initSanitaryPayment() throws Exception{
        List<TPropertyRoom> roomList = roomMapper.selectByExample(null);
        //卫生费
        for(TPropertyRoom tPropertyRoom : roomList) {
            String roomNum = tPropertyRoom.getRoomNum();
            BigDecimal square = tPropertyRoom.getSquare();
            String currentMonth = DateUtil.getNowShortDate().substring(0, 6);

            PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
            paymentQueryReq.setType(PaymentTypeEnum.SANITARY_FEE.getCode());
            paymentQueryReq.setRoomNum(roomNum);
            paymentQueryReq.setFeeDate(currentMonth);
            PaymentQueryResp paymentQueryResp = findPaymentRecord(paymentQueryReq);
            if (null != paymentQueryResp) {
                continue;
            }
            TPropertyFeeConfig sanitaryFeeConfig = feeConfigService.findFeeConfigByType(PaymentTypeEnum.SANITARY_FEE.getCode());
            BigDecimal sanitaryRate = sanitaryFeeConfig.getFee();
            BigDecimal sanitaryFee = sanitaryRate.multiply(square);
            PaymentAddReq paymentAddReq = new PaymentAddReq();
            paymentAddReq.setRoomNum(roomNum);
            paymentAddReq.setAmount(sanitaryFee);
            paymentAddReq.setFeeDate(currentMonth);
            paymentAddReq.setStatus(PaymentStatusEnum.NO_PAY.getCode());
            paymentAddReq.setType(PaymentTypeEnum.SANITARY_FEE.getCode());
            addPayment(paymentAddReq);
        }

    }

    /**
     *  处理物业费
     */
    public void initPropertyPayment() throws Exception{
        List<TPropertyRoom> roomList = roomMapper.selectByExample(null);
        //物业费
        for(TPropertyRoom tPropertyRoom : roomList){
            String roomNum = tPropertyRoom.getRoomNum();
            BigDecimal square = tPropertyRoom.getSquare();
            String currentMonth = DateUtil.getNowShortDate().substring(0 , 6);

            PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
            paymentQueryReq.setType(PaymentTypeEnum.PROPERTY_FEE.getCode());
            paymentQueryReq.setRoomNum(roomNum);
            paymentQueryReq.setFeeDate(currentMonth);
            PaymentQueryResp paymentQueryResp = findPaymentRecord(paymentQueryReq);
            if(null != paymentQueryResp){
                continue;
            }

            TPropertyFeeConfig propertyFeeConfig = feeConfigService.findFeeConfigByType(PaymentTypeEnum.PROPERTY_FEE.getCode());
            BigDecimal propertyRate = propertyFeeConfig.getFee();
            BigDecimal propertyFee = propertyRate.multiply(square);
            PaymentAddReq paymentAddReq = new PaymentAddReq();
            paymentAddReq.setAmount(propertyFee);
            paymentAddReq.setType(PaymentTypeEnum.PROPERTY_FEE.getCode());
            paymentAddReq.setRoomNum(roomNum);
            paymentAddReq.setFeeDate(currentMonth);
            paymentAddReq.setStatus(PaymentStatusEnum.NO_PAY.getCode());
            addPayment(paymentAddReq);

        }

    }

    /**
     *  处理管卫费
     */
    @Transactional(rollbackFor = Exception.class)
    public void initManagePayment() throws Exception{
        List<TPropertyRoom> roomList = roomMapper.selectByExample(null);
        //物业费
        for(TPropertyRoom tPropertyRoom : roomList){
            String roomNum = tPropertyRoom.getRoomNum();
            BigDecimal square = tPropertyRoom.getSquare();
            String currentMonth = DateUtil.getNowShortDate().substring(0 , 6);

            PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
            paymentQueryReq.setType(PaymentTypeEnum.MANAGE_FEE.getCode());
            paymentQueryReq.setRoomNum(roomNum);
            paymentQueryReq.setFeeDate(currentMonth);
            PaymentQueryResp paymentQueryResp = findPaymentRecord(paymentQueryReq);
            if(null != paymentQueryResp){
                continue;
            }

            TPropertyFeeConfig propertyFeeConfig = feeConfigService.findFeeConfigByType(PaymentTypeEnum.MANAGE_FEE.getCode());
            BigDecimal propertyRate = propertyFeeConfig.getFee();
            BigDecimal propertyFee = propertyRate.multiply(square)
                    .add(new BigDecimal(BusinessConstants.REPAIRMENT_FEE))
                    .add(new BigDecimal(BusinessConstants.SANITARY_FEE))
                    ;
            PaymentAddReq paymentAddReq = new PaymentAddReq();
            paymentAddReq.setAmount(propertyFee);
            paymentAddReq.setType(PaymentTypeEnum.MANAGE_FEE.getCode());
            paymentAddReq.setRoomNum(roomNum);
            paymentAddReq.setFeeDate(currentMonth);
            paymentAddReq.setStatus(PaymentStatusEnum.NO_PAY.getCode());
            paymentAddReq.setStartTime(DateUtil.getCurrentFirstDate());
            paymentAddReq.setEndTime(DateUtil.getCurrentLastDate());
            addPayment(paymentAddReq);
        }

    }

    public void pushMsgToOwners(PaymentNotifyReq paymentNotifyReq) throws Exception{
        String type = paymentNotifyReq.getType();
        String roomNum = paymentNotifyReq.getRoomNum();
        PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
        paymentQueryReq.setType(type);
        paymentQueryReq.setRoomNum(roomNum);
        paymentQueryReq.setFeeDate(DateUtil.getNowShortDate().substring(0 , 6));
        paymentQueryReq.setStatus(PaymentStatusEnum.NO_PAY.getCode());
        PaymentQueryResp paymentQueryResp = findPaymentRecord(paymentQueryReq);
        if(null == paymentQueryResp){
            throw new BaseException("当前业主当月不存在待缴费记录");
        }

        JSONObject jsonMsg = new JSONObject();
        Map<String , Map<String , String>> dataMap = Maps.newHashMap();
        Map<String , String> keyword1Map = Maps.newHashMap();
        keyword1Map.put("value" , PaymentTypeEnum.getActivityCode(paymentNotifyReq.getType()).getDesc());
        dataMap.put("keyword1" ,keyword1Map);

        Map<String , String> keyword2Map = Maps.newHashMap();
        keyword2Map.put("value" , paymentQueryResp.getAmount() + "元");
        dataMap.put("keyword2" ,keyword2Map);

        Map<String , String> keyword3Map = Maps.newHashMap();
        keyword3Map.put("value" , roomNum);
        dataMap.put("keyword3" ,keyword3Map);

        Map<String , String> keyword4Map = Maps.newHashMap();
        keyword4Map.put("value" , "雅怡居");
        dataMap.put("keyword4" ,keyword4Map);

        Map<String , String> keyword5Map = Maps.newHashMap();
        String feeDate = paymentQueryResp.getFeeDate();
        String feeDate_ = feeDate.substring(0 , 4) + "年" +  (feeDate.substring(4 , 6).startsWith("0") ? feeDate.substring(5 , 6) : feeDate.substring(4 , 6)) + "月";
        keyword5Map.put("value" , feeDate_);
        dataMap.put("keyword5" ,keyword5Map);

        Map<String , String> keyword6Map = Maps.newHashMap();
        keyword6Map.put("value" , "请及时完成交费");
        dataMap.put("keyword6" ,keyword6Map);

        Map<String , String> keyword7Map = Maps.newHashMap();
        keyword7Map.put("value" ,"点击查看详细交费数据");
        dataMap.put("keyword7" ,keyword7Map);

        jsonMsg.put("data" , dataMap);

        List<TPropertyOwner> ownerList = userService.findOwnersByRoomNum(roomNum);
        for(TPropertyOwner owner : ownerList){
            String openId = owner.getOpenId();
            if(StringUtils.isBlank(openId) || openId.startsWith("wx-")){
                continue;
            }
            jsonMsg.put("touser" , openId);
            jsonMsg.put("template_id" , configService.getConfigInfo("PAYMENT_MSG_TEMPLATE_ID").getConfigAttr());
            TPropertyUserForm userForm = userFormService.queryUserForm(openId);
            if(null == userForm){
                continue;
            }
            jsonMsg.put("form_id" , userForm.getFormId());
            String feeType = "";
            if(PaymentTypeEnum.WATER_FEE.getCode().equals(paymentNotifyReq.getType())){
                feeType = "water";
            }
            if(PaymentTypeEnum.MANAGE_FEE.getCode().equals(paymentNotifyReq.getType())){
                feeType = "manage";
            }
            jsonMsg.put("page" , configService.getConfigInfo("PAYMENT_MSG_PAGE_URL").getConfigAttr()
                    .replace("FEETYPE" , feeType)
                    .replace("STATUS" , "NO_PAY")
                    .replace("FEEDATE" , DateUtil.getNowShortDate().substring(0 , 6))
            );
            WeixinUtil.sendTemplateMsg(appService.getAccessToken() , jsonMsg);
        }

    }

    public void pushMsgToOwners(PaymentNotifyReq paymentNotifyReq , String openId) throws Exception{
        String type = paymentNotifyReq.getType();
        String roomNum = paymentNotifyReq.getRoomNum();
        PaymentQueryReq paymentQueryReq = new PaymentQueryReq();
        paymentQueryReq.setType(type);
        paymentQueryReq.setRoomNum(roomNum);
        paymentQueryReq.setFeeDate(DateUtil.getNowShortDate().substring(0 , 6));
        PaymentQueryResp paymentQueryResp = findPaymentRecord(paymentQueryReq);
        if(null == paymentQueryResp){
            throw new BaseException("当前业主当月不存在待缴费记录");
        }

        JSONObject jsonMsg = new JSONObject();
        Map<String , Map<String , String>> dataMap = Maps.newHashMap();
        Map<String , String> keyword1Map = Maps.newHashMap();
        keyword1Map.put("value" , "尊敬的【"+ roomNum + "】单元业主，您有" + paymentQueryResp.getAmount().toString() + "元" + PaymentTypeEnum.getActivityCode(type).getDesc() + "未交，请记得缴费哦");
        keyword1Map.put("color" , "#0033FF");
        dataMap.put("keyword1" ,keyword1Map);
        jsonMsg.put("data" , dataMap);

        List<TPropertyOwner> ownerList = userService.findOwnersByRoomNum(roomNum);
        for(TPropertyOwner owner : ownerList){
            jsonMsg.put("touser" , openId);
            jsonMsg.put("template_id" , configService.getConfigInfo("SEND_MSG_TEMPLATE_ID").getConfigAttr());
            jsonMsg.put("page" , configService.getConfigInfo("TEMPLATE_MSG_PAGE").getConfigAttr()
                    .replace("STATUS" , "NO_PAY")
                    .replace("FEEDATE" , DateUtil.getNowShortDate().substring(0 , 6))
            );
            WeixinUtil.sendTemplateMsg(appService.getAccessToken() , jsonMsg);
        }

    }


    public PageRspData<BackendPaymentListResp> findBackendPaymentList(BackendPaymentListReq req) throws Exception {
        Page page = PageHelper.startPage(req.getCurrentPage(), req.getPageSize());
        List<BackendPaymentListResp> list = paymentMapper.queryBackendPaymentList(req);
        List<BackendPaymentListResp> paymentList = Lists.newArrayList();
        for(BackendPaymentListResp backendPaymentListResp : list){
            if(PaymentTypeEnum.WATER_FEE.getCode().equals(backendPaymentListResp.getType())){
                TPropertyWaterBill waterBill = waterBillService.queryWaterBillDetail(backendPaymentListResp.getWaterBillId());
                String endTime = null == backendPaymentListResp.getAuditTime() ? "" : backendPaymentListResp.getAuditTime();
                backendPaymentListResp.setStartStopTime(DateUtil.format(waterBill.getCreateTime() ,sdfLongTimePlus ) + "-" + endTime);
                if(null != waterBill){
                    backendPaymentListResp.setReadNum(waterBill.getMultiReadNum());
                }
            }else{
                backendPaymentListResp.setStartStopTime(backendPaymentListResp.getStartTime() + "-" + backendPaymentListResp.getEndTime());
            }
            paymentList.add(backendPaymentListResp);
        }
        PageRspData<BackendPaymentListResp> pageRspData = new PageRspData<BackendPaymentListResp>(
                page.getTotal(), req.getCurrentPage(), req.getPageSize(), paymentList);
        return pageRspData;
    }

    public String getPaymentInfo(SessionInfo sessionInfo){
        String roomNum = sessionInfo.getRoomNum();
        TPropertyRoom tPropertyRoom = roomService.queryRoomByNum(roomNum);
        BigDecimal square = tPropertyRoom.getSquare();
        BigDecimal manageFeeRate = feeConfigService.findFeeConfigByType("MANAGE_FEE").getFee();
        BigDecimal manageFee = square.multiply(manageFeeRate).setScale(2 , BigDecimal.ROUND_HALF_UP);
        BigDecimal repairFee = new BigDecimal(BusinessConstants.REPAIRMENT_FEE);
        BigDecimal sanitaryFee = new BigDecimal(BusinessConstants.SANITARY_FEE);
        BigDecimal finalFee = manageFee.add(repairFee).add(sanitaryFee).setScale(2 , BigDecimal.ROUND_HALF_UP);
        String content = roomNum + "业主，住户面积" + square + "平方米，其中管理费" + manageFee + "元/月（住户面积*0.8）、卫生费"
                + sanitaryFee + "元/月、维修费" + repairFee + "元/月，合计" + finalFee + "元/月"
                ;
        return content;
    }

    public static void main(String[] args) throws ParseException {
        String feeDate = "201702";
        System.out.println(feeDate.substring(4 , 6).startsWith("0") ? feeDate.substring(5 , 6): feeDate.substring(4 , 6));
        String roomNum = "A1110";
        System.out.println(roomNum.substring(0 , 2) + "-" + roomNum.substring(2 ,5));

        Date date = DateUtil.increaseDay(DateUtil.increaseMonth(DateUtil.getDateYMD() , 1) , -1);
        System.out.println(DateUtil.getDateYMD().toLocaleString());
        System.out.println(date.toLocaleString());

        // 获取当月第一天和最后一天
        System.out.println(DateUtil.getCurrentFirstDate().toLocaleString());

        System.out.println(DateUtil.getCurrentLastDate().toLocaleString());

    }

}
